package com.ray.auth.system.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.flyong.cache.query.cache.CacheConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ray.auth.system.emun.BtnType;
import com.ray.auth.system.emun.LinkType;
import com.ray.auth.system.emun.UseStatus;
import com.ray.auth.system.service.ButtonService;
import com.ray.auth.system.service.MenuService;
import com.ray.auth.system.service.RoleService;
import com.ray.auth.system.service.UserGroupService;
import com.ray.auth.system.table.customMapper.CustomButtonMapper;
import com.ray.auth.system.table.entity.Button;
import com.ray.auth.system.table.entity.ButtonExample;
import com.ray.auth.system.table.entity.ButtonExample.Criteria;
import com.ray.auth.system.table.entity.ButtonRel;
import com.ray.auth.system.table.entity.ButtonRelExample;
import com.ray.auth.system.table.mapper.ButtonMapper;
import com.ray.auth.system.table.mapper.ButtonRelMapper;
import com.ray.auth.system.vo.MenuParams;
import com.xiaoleilu.hutool.util.ObjectUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import com.zjhc.flyhong.common.function.enums.DeleteEnum;
import com.zjhc.flyhong.common.function.exception.BussinessException;
import com.zjhc.flyhong.common.function.operator.LoginUser;
import com.zjhc.flyhong.common.function.operator.PageDto;
import com.zjhc.flyhong.common.function.validate.EntityValidate;
import com.zjhc.flyhong.common.function.validate.rule.FieldRule;
import com.zjhc.flyhong.common.function.validate.rule.RuleEnum;
import com.zjhc.flyhong.common.util.UUIDUtil;
import com.zjhc.flyhong.common.web.ErrorMsg;
import com.zjhc.flyhong.common.web.Result;
import com.zjhc.flyhong.common.web.ResultHelper;
import com.zjhc.flyhong.common.web.SuccessMsg;
import com.zjhc.flyhong.common.web.base.BaseService;

/**
 * <h1>系统权限应用 资源 服务实现</h1>
 * 
 * @创建人 ray
 * @创建时间 2017-06-10
 * @版本 1.0
 * @重要修改备注
 * 
 */
@Service
public class ButtonServiceImpl extends BaseService implements ButtonService {
	/**日志对象**/
	private static Logger logger = Logger.getLogger(ButtonServiceImpl.class);
	/************** 实现类 其他对象 引用 开始 ***********************/
	/** 应用数据库操作对象 **/
	@Autowired
	private ButtonMapper buttonMapper;
	@Autowired
	private ButtonRelMapper buttonRelMapper;
	/** 菜单关联数据库操作 **/
	@Autowired
	private CustomButtonMapper customButtonMapper;
	/** 用户组数据库操作 **/
	@Autowired
	private UserGroupService userGroupService;
	/** 角色数据库操作 **/
	@Autowired
	private RoleService roleService;
	/** 菜单数据库操作 **/
	@Autowired
	private MenuService menuService;
	/**
	 * 获取用户资源下授权的 资源 包括用户、用户组、角色
	 * 
	 * @param userId
	 *            用户ID
	 * @return 菜单资源
	 */
	@CacheConfig(key="buttonList",query=true,paramsSize=1,expire=60)
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> queryUserButtons(String userId,String appid) {
		List<Button> list = new ArrayList<Button>();
		// 获取用户下的menu资源
		list.addAll(this.queryButtonsByLinkType(userId,appid, LinkType.USER));
		// 获取用户所在的用户组
		List<String> userGroupIds = userGroupService.queryGroupsAllByUserId(userId);
		// 获取用户组下所有meunu资源
		for (String userGroupId : userGroupIds) {
			list.addAll(this.queryButtonsByLinkType(userGroupId,appid, LinkType.USERGROUP));
		}
		// 获取用户所在用户组的角色ID
		for (String userGroupId : userGroupIds) {
			// 获取用户组下的角色
			List<String> roleIds = roleService.queryRoleByUserGroupId(userGroupId);
			// 获取角色下所有meunu资源
			for (String roleId : roleIds) {
				list.addAll(this.queryButtonsByLinkType(roleId,appid, LinkType.ROLE));
			}
		}
		// 获取用户所拥有的角色
		List<String> roleIds = roleService.queryRoleByUserId(userId);
		// 获取角色下所有meunu资源
		for (String roleId : roleIds) {
			list.addAll(this.queryButtonsByLinkType(roleId,appid, LinkType.ROLE));
		}
		return list;
	}

	/**
	 * 通过关联ID和关联类型 获取对应的菜单资源
	 * 
	 * @param linkId
	 *            关联ID
	 * @param linkType
	 *            关联类型
	 * @return 菜单资源
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> queryButtonsByLinkType(String linkId,String appid, LinkType linkType) {
		return customButtonMapper.selectButtonByLink(linkId,appid, linkType.getType(),UseStatus.ON.getType(), DeleteEnum.USE.getValue());
	}

	/**
	 * 通过关联ID和关联类型 获取对应的菜单资源
	 * 
	 * @param linkId
	 *            关联ID
	 * @param linkType
	 *            关联类型
	 * @param menuId
	 *            菜单
	 * @return 菜单资源
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> queryButtonsByLinkTypeWithMenuId(String linkId, LinkType linkType, String menuId) {
		return customButtonMapper.selectButtonByLinkWithMenuId(linkId, linkType.getType(), menuId,
				UseStatus.ON.getType(),DeleteEnum.USE.getValue());
	}

	/**
	 * 获取超级用户资源下授权的 资源 包括用户、用户组、角色
	 * 
	 * @param userId
	 *            用户ID
	 * @return 资源
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> querySuperUserButtons(String appid) {
		ButtonExample buttonExample = new ButtonExample();
		buttonExample.createCriteria().andIsDeleteEqualTo(DeleteEnum.USE.getValue())
		.andAppIdEqualTo(appid);
		return buttonMapper.selectByExample(buttonExample);
	}

	/**
	 * 获取超级用户资源下授权的 资源 包括用户、用户组、角色
	 * 
	 * @param userId
	 *            用户
	 * @param menuId
	 *            菜单
	 * @return
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public Map<String, List<Button>> queryUserButtonsWithMenu(LoginUser loginUser, String menuId) {
		if(StrUtil.isBlank(menuId)){
			return  new HashMap<String, List<Button>>();
		}
		if(loginUser.isSuperManager()){
			return querySuperManageButtonsWithMenu(loginUser.getUserId(),menuId,BtnType.BTN);
		}else{
			return queryButtonsWithMenu(loginUser.getUserId(),menuId);
		}
	}
	/**
	 * 获取系统管理员 全部权限
	 * @param userId
	 * @param menuId
	 * @return
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	private Map<String, List<Button>> querySuperManageButtonsWithMenu(String userId, String menuId,BtnType btnType) {
		Map<String, List<Button>> result = new HashMap<String, List<Button>>();
		List<Button> list = queryButtonsByMenuId(menuId,btnType);
		// 分组
		List<String> menuIds = new ArrayList<String>();
		for (Button button : list) {
			// 去除重复数据
			if (menuIds.contains(button.getMenuId()))
				continue;
			List<Button> btns = result.get(button.getGroupName());
			if (ObjectUtil.isNull(btns)) {
				btns = new ArrayList<Button>();
			}
			btns.add(button);
			result.put(button.getGroupName(), btns);
		}
		return result;
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> queryButtonsByMenuId(String menuId,BtnType btnType) {
		ButtonExample example = new ButtonExample();
		Criteria criteria  = example.createCriteria();
		criteria.andMenuIdEqualTo(menuId)
		.andButtonStatusEqualTo(UseStatus.ON.getType())
		.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		if(btnType != null){
			criteria.andButtonTypeEqualTo(btnType.getType());
		}
		example.setOrderByClause("index_sort asc");
		return buttonMapper.selectByExample(example);
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> queryAllButtonsByMenuId(String menuId) {
		ButtonExample example = new ButtonExample();
		Criteria criteria  = example.createCriteria();
		criteria.andMenuIdEqualTo(menuId)
		.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		return buttonMapper.selectByExample(example);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	private Map<String, List<Button>> queryButtonsWithMenu(String userId, String menuId) {
		Map<String, List<Button>> result = new HashMap<String, List<Button>>();
		List<Button> list = new ArrayList<Button>();
		// 获取用户下的menu资源
		list.addAll(this.queryButtonsByLinkTypeWithMenuId(userId, LinkType.USER, menuId));
		// 获取用户所在的用户组
		List<String> userGroupIds = userGroupService.queryGroupsAllByUserId(userId);
		// 获取用户组下所有meunu资源
		for (String userGroupId : userGroupIds) {
			list.addAll(this.queryButtonsByLinkTypeWithMenuId(userGroupId, LinkType.USERGROUP, menuId));
		}
		// 获取用户所在用户组的角色ID
		for (String userGroupId : userGroupIds) {
			// 获取用户组下的角色
			List<String> roleIds = roleService.queryRoleByUserGroupId(userGroupId);
			// 获取角色下所有meunu资源
			for (String roleId : roleIds) {
				list.addAll(this.queryButtonsByLinkTypeWithMenuId(roleId, LinkType.ROLE, menuId));
			}
		}
		// 获取用户所拥有的角色
		List<String> roleIds = roleService.queryRoleByUserId(userId);
		// 获取角色下所有meunu资源
		for (String roleId : roleIds) {
			list.addAll(this.queryButtonsByLinkTypeWithMenuId(roleId, LinkType.ROLE, menuId));
		}
		// 分组
		List<String> buttonIds = new ArrayList<String>();
		for (Button button : list) {
			// 去除重复数据
			if (buttonIds.contains(button.getButtonId()))
				continue;
			buttonIds.add(button.getButtonId());
			List<Button> btns = result.get(button.getGroupName());
			if (ObjectUtil.isNull(btns)) {
				btns = new ArrayList<Button>();
			}
			if(StrUtil.equals(button.getButtonType(), BtnType.GN.getType()))continue;
			
			btns.add(button);
			//按钮排序
			 Collections.sort(btns, new Comparator() {
			  	public int compare(Object o1, Object o2) {
			        return ((Button)o1).getIndexSort()-((Button)o2).getIndexSort();
			      }
			    });
			result.put(button.getGroupName(), btns);
		}
		return result;
	}

	/**
	 * 查询所有从按钮
	 * @param params 查询参数
	 * @param page 分页信息
	 * @param loginUser 登录用户
	 * @return
	 */
	
	@CacheConfig(key="buttonList",query=true,paramsSize=2,expire=60)
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public PageDto<Button> queryButtonList(Button params, PageDto<Button> page, LoginUser loginUser) {
		ButtonExample example = new ButtonExample();
		Criteria criteria =  example.createCriteria();
		//超级管理员不需要租户
		if(!loginUser.isSuperManager()){
			criteria.andTenantIdEqualTo(loginUser.getTenantId());
		}
		if(StrUtil.isNotBlank(params.getMenuId())){
			criteria.andMenuIdEqualTo(params.getMenuId());
		}
		criteria.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		this.setExamplePage(example, page);
		page.setTotal(buttonMapper.countByExample(example));
		page.setRecords(buttonMapper.selectByExample(example));
		return page;
	}
	
	/**
	 * 通过主键删除按钮数据
	 * @param id 主键
	 * @param loginUser 操作用户
	 * @return
	 */
	
	@CacheConfig(key="button",paramsSize=1,delete=true, clearKey="buttonList")
	@Transactional
	public Result<Object> deleteButton(String id, LoginUser loginUser) {
		Result<Object> result = null;
		result = new Result<Object>(0,SuccessMsg.OP_SUCCESS);
		Button record = new Button();
		record.setButtonId(id);
		record.setIsDelete(DeleteEnum.DELETE.getValue());
		this.setUserForUpdate(record, loginUser);
		int opCount = buttonMapper.updateByPrimaryKeySelective(record);
		if(opCount != 1){
			logger.error("ButtonServiceImpl=>deleteButton is error");
			throw new BussinessException(-1, ErrorMsg.DELETE_ERROR);
		}
		//删除按钮关联
		deleteButtonRel(id, loginUser);
		return result;
	}

	/***
	 * @描述 <h1>添加菜单</h1><br/>数据库操作信息从  Operater对象中获取.
	 * @参数 entity 菜单对象
	 * @参数 operater 操作人信息
	 * @异常    内部捕获异常
	 * @事物    异常=>事物进行回滚
	 * @返回 result  返回结果  result.status => 0表示成功 ,其余表示失败
	 */
	@Transactional
	public Result<Object> saveButton(Button entity, LoginUser loginUser) {
		//对象验证 
		/*****************验证开始************************/	
		FieldRule fieldRule = new FieldRule();
		fieldRule.addRule(RuleEnum.IS_NOT_NULL, String.class, "buttonName","按钮名称")
		.addRule(RuleEnum.IS_NOT_NULL, String.class, "url","请求路径")
		.addRule(RuleEnum.IS_NOT_NULL, String.class, "authUrl","权限路径");
		Result<Object> rs =	EntityValidate.validate(entity, fieldRule);
		if(!rs.codeSuccess())return rs;
		/******************验证结束*******************/
		entity.setTenantId(loginUser.getTenantId());
		entity.setButtonId(UUIDUtil.getUUID());
		entity.setIsDelete(DeleteEnum.USE.getValue());
		entity.setAppId(menuService.getAppId(entity.getMenuId()));
		this.setUserForAdd(entity, loginUser);
		//执行成功数量	
		int exeCount = buttonMapper.insertSelective(entity);
		if(exeCount != 1)return ResultHelper.getError();
		return ResultHelper.getSuccess();
	}

	
	@CacheConfig(key="button",paramsSize=1,expire=1800)
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public Button queryButton(String id, LoginUser loginUser) {
		return buttonMapper.selectByPrimaryKey(id);
	}

	
	@CacheConfig(key="button",paramsSize=1,update=true, id="buttonId", clearKey="buttonList")
	@Transactional
	public Result<Object> updateButton(Button record, LoginUser loginUser) {
		Result<Object> result = null;
		result = new Result<Object>(0,SuccessMsg.OP_SUCCESS);
		this.setUserForUpdate(record, loginUser);
		int opCount = buttonMapper.updateByPrimaryKeySelective(record);
		if(opCount != 1){
			logger.error("ButtonServiceImpl=>buttonUpdate is error");
			throw new BussinessException(-1, ErrorMsg.UPDATE_ERROR);
		}
		return result;
	}

	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> queryUserOnwerButtons(String userId, LoginUser loginUser) {
		ButtonExample example = new ButtonExample();
		example.createCriteria()
		//.andTenantIdEqualTo(loginUser.getTenantId())
		.andButtonStatusEqualTo(UseStatus.ON.getType())
		.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		MenuParams params  = new MenuParams();
		params.setUserId(userId);
		List<Button> list = customButtonMapper.selectMyButton(example, params);
		return list;
	}

	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public List<Button> queryRoleOnwerButtons(String roleId, LoginUser loginUser) {
		ButtonExample example = new ButtonExample();
		example.createCriteria()
		//.andTenantIdEqualTo(loginUser.getTenantId())
		.andButtonStatusEqualTo(UseStatus.ON.getType())
		.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		MenuParams params  = new MenuParams();
		params.setRoleId(roleId);
		params.setIsDelete(DeleteEnum.USE.getValue());
		params.setRoleType(LinkType.ROLE.getType());
		params.setStatus(UseStatus.ON.getType());
		List<Button> list = customButtonMapper.selectRoleButton(example, params);
		return list;
	}
	
	 /**
     * 新增菜单关联
     * @param menuId
     * @param linkId
     * @param type
     * @param loginUser
     * @return
     */
	@Transactional
	public Result<Object> addButtonRel(String buttonId, String linkId, String type, LoginUser loginUser){
		//对象验证 
		/*****************验证开始************************/	
		EntityValidate.isNotNull(buttonId, "按钮编号");
		EntityValidate.isNotNull(linkId, "关联编号");
		EntityValidate.isNotNull(type, "关联类型");
		if(ObjectUtil.isNotNull(queryButtonRel(buttonId, linkId, type, loginUser))){
			return ResultHelper.getError(-1,"关联已经存在.");
		}
		/******************验证结束*******************/
		ButtonRel entity = new ButtonRel();
		entity.setTenantId(loginUser.getTenantId());
		entity.setId(UUIDUtil.getUUID());
		entity.setIsDelete(DeleteEnum.USE.getValue());
		entity.setButtonId(buttonId);
		entity.setLinkId(linkId);
		entity.setLinkType(type);
		this.setUserForAdd(entity, loginUser);
		//执行成功数量	
		int exeCount = buttonRelMapper.insertSelective(entity);
		if(exeCount != 1)return ResultHelper.getError();
		return ResultHelper.getSuccess();
	}
    /**
     * 判断菜单关联
     * @param menuId
     * @param roleId
     * @param type
     * @param loginUser
     * @return
     */
	@Transactional
	public Result<Object> deleteButtonRel(String buttonId, String linkId, String type, LoginUser loginUser){
		Result<Object> result = null;
		result = new Result<Object>(0,SuccessMsg.OP_SUCCESS);
		ButtonRel record = new ButtonRel();
		record.setIsDelete(DeleteEnum.DELETE.getValue());
		this.setUserForUpdate(record, loginUser);
		ButtonRelExample example = new ButtonRelExample();
		example.createCriteria().andButtonIdEqualTo(buttonId)
		.andLinkIdEqualTo(linkId).andLinkTypeEqualTo(type)
		.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		int opCount = buttonRelMapper.updateByExampleSelective(record, example);
		if(opCount != 1){
			logger.error("ButtonServiceImpl=>deleteButtonRel is error");
			throw new BussinessException(-1, ErrorMsg.DELETE_ERROR);
		}
		return result;
	}
	/**
     * 查询按钮关联
     * @param menuId
     * @param roleId
     * @param type
     * @param loginUser
     * @return
     */
	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	public ButtonRel queryButtonRel(String buttonId, String linkId, String type, LoginUser loginUser){
		ButtonRel params = new ButtonRel();
		params.setButtonId(buttonId);
		params.setLinkId(linkId);
		params.setLinkType(type);
		params.setIsDelete(DeleteEnum.USE.getValue());
		List<ButtonRel> list = buttonRelMapper.selectByRecord(params);
		if(list == null || list.size() == 0){
			return null;
		}
		if(list.size() > 1){
		  logger.error("queryButtonRel> too maney reocrd to query.");
		  throw new BussinessException(-1, ErrorMsg.SYS_IN_ERROR);
		}
		return list.get(0);	
	}

	@Override
	@Transactional
	public void deleteButtonByMenuId(String menuId, LoginUser loginUser) {
		List<Button> buttons = this.queryAllButtonsByMenuId(menuId);
		for(Button button : buttons){
			//删除按钮
			this.deleteButton(button.getButtonId(), loginUser);
		}
		
	}
	
	 /**
	  * 删除按钮关联
	  * @param id
	  * @param loginUser
	  */
	@Transactional
	 private void deleteButtonRel(String id, LoginUser loginUser) {
	    ButtonRel record = new ButtonRel();
		record.setIsDelete(DeleteEnum.DELETE.getValue());
		this.setUserForUpdate(record, loginUser);
		ButtonRelExample example = new ButtonRelExample();
		example.createCriteria().andButtonIdEqualTo(id);
		buttonRelMapper.updateByExampleSelective(record, example);
	}
	 
}
